VIDEO_SELECTOR equ 0x0018

[bits 32]
section .text

;=====================================================
global print_char
print_char:
	pushad
	
	mov ax, VIDEO_SELECTOR
	mov gs, ax
	
	; get current cursor to bx
	mov dx, 0x3d4
	mov al, 0x0e
	out dx, al
	mov dx, 0x3d5
	in al, dx
	mov ah, al
	
	mov dx, 0x3d4
	mov al, 0x0f
	out dx, al
	mov dx, 0x3d5
	in al, dx
	mov bx, ax
	
	; mov print char to cl
	mov cl, [esp+36]
	
	cmp cl, 0x0a ; '\n'
	jz .print_new_line
	
	cmp cl, 0x0d ; '\r'
	jz .print_new_line
	
	cmp cl, 0x08
	jz .print_back_space
	
	; visiable char
	shl bx, 1
	mov [gs:bx+0x00], cl
	mov byte [gs:bx+0x01], 0x07
	shr bx, 1
	add bx, 1
	
	jmp .update_cursor
	
.print_new_line:
	xor dx, dx
	mov ax, bx
	mov di, 80
	div di
	add ax, 1
	mov di, 80
	mul di
	mov bx, ax
	
	jmp .update_cursor
	
.print_back_space:
	cmp bx, 0
	jz .update_cursor
	
	sub bx, 1
	shl bx, 1
	mov byte [gs:bx+0x00], ' '
	mov byte [gs:bx+0x01], 0x07
	shr bx, 1
	
	jmp .update_cursor

.update_cursor:
	; check roll screen
	cmp bx, 2000
	jnz .set_cursor
	
	mov ecx, 960
	mov esi, 0xA0
	mov edi, 0x0
.copy_video_mem:
	mov eax, [gs:esi]
	mov [gs:edi], eax
	add esi, 4
	add edi, 4
	loop .copy_video_mem
	
	mov ecx, 80
	mov esi, 0xF00
.clear_last_line:
	mov byte [gs:esi+0x00], ' '
	mov byte [gs:esi+0x01], 0x07
	add esi, 2
	loop .clear_last_line
	
	sub bx, 80
	
.set_cursor:
	mov dx, 0x3d4
	mov al, 0x0e
	out dx, al
	mov dx, 0x3d5
	mov al, bh
	out dx, al
	
	mov dx, 0x3d4
	mov al, 0x0f
	out dx, al
	mov dx, 0x3d5
	mov al, bl
	out dx, al
	
	popad
	ret
	
;=====================================================
global print_string
print_string:
	push ebx
	push ecx
	push edx
	
	; mov const char* to ebx
	mov ebx, [esp+16]
	
	xor ecx, ecx
	xor edx, edx
	
	mov dl, [ebx] ; print char
	cmp dl, 0
	jz .push_string_ret
.print_char:
	push edx
	call print_char
	add esp, 4
	add ecx, 1
	
	mov dl, [ebx+ecx] ; print char
	cmp dl, 0
	jnz .print_char

.push_string_ret:
	pop edx
	pop ecx
	pop ebx
	ret
	
;=====================================================
global print_hex
print_hex:
	push ebp
	mov ebp, esp
	push ebx
	push ecx
	push edx
	push edi
	
	sub esp, 12 ; buf
	mov edi, esp
	
	mov byte [edi], '0'
	mov byte [edi+1], 'x'
	
	xor edx, edx
	
	mov ebx, [ebp+8] ; print int
	mov ecx, 8
.loop_print_hex:
	mov dl, bl
	and dl, 0x0f
	cmp dl, 9
	jg .print_a_f
	
.print_0_9:
	add dl, '0'
	mov [edi+2+ecx-1], dl
	jmp .next
.print_a_f:
	sub dl, 10
	add dl, 'A'
	mov [edi+2+ecx-1], dl
	
.next:
	shr ebx, 4
	loop .loop_print_hex
	
	mov byte [edi+10], 0
	push esp
	call print_string
	add esp, 4
	
	add esp, 12
	pop edi
	pop edx
	pop ecx
	pop ebx
	pop eax
	leave
	ret
	
;=====================================================
global set_cursor
set_cursor:
	pushad
	mov bx, [esp+36]
	
	; high 8 bit
	mov dx, 0x03d4
	mov al, 0x0e
	out dx, al
	mov dx, 0x03d5
	mov al, bh
	out dx, al

	; low 8 bit
	mov dx, 0x03d4
	mov al, 0x0f
	out dx, al
	mov dx, 0x03d5
	mov al, bl
	out dx, al
	
	popad
	ret

